package org.raymond.iworks.study.basic.thread.forkjoinpool;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

@Slf4j
public class Demo2 {
    private static long num = 59999999999L;
    public static void main(String[] args) {
        test1(); // 耗时: 20s, cpu占用:core i5 4核 30%~13%
        test2(); // 耗时: 10s, cpu占用:core i5 4核 98%
    }

    public static void test1(){
        //开始时间
        Long start = System.currentTimeMillis();
        long sum = 0l;
        for (long i = 1; i <= num; i++) {
            sum+=i;
        }
        log.info("{}", sum); //结果为负数,因为超出了long的最大值了   ,平均消耗时间:16秒
        //结束时间
        Long end = System.currentTimeMillis();
        log.info("消耗时间: {}", (end-start));
    }
    public static void test2(){
        Long start = System.currentTimeMillis();
        //放入线程池
        ForkJoinPool pool = new ForkJoinPool();
        SumRecursiveTask task = new SumRecursiveTask(1, num);
        Long result = pool.invoke(task);
        log.info("result: {}", result); //结果为负数,因为超出了long的最大值了   ,平均消耗时间:4秒
        Long end = System.currentTimeMillis();
        log.info("消耗时间: {}", (end-start));
    }

    static public class SumRecursiveTask extends RecursiveTask<Long> {
        //大于3000要拆分(创建一个变量)
        //是否要拆分的临界值
        private static final long THRESHOLD = 3000L;

        //起始值
        private final long start;
        //结束值
        private final long end;

        //构造方法(传递起始值、结束值)
        public SumRecursiveTask(long start, long end) {
            this.start = start;
            this.end = end;
        }

        @Override
        protected Long compute() {
            long length = end - start;
            //计算
            if(length < THRESHOLD){
                long sum = 0;
                for (long i = start; i <= end; i++) {
                    sum +=i;
                }
                return sum;
            }else{
                //拆分
                long middle = (start + end) /2;
                SumRecursiveTask left = new SumRecursiveTask(start,middle);//从小到大
                left.fork();
                SumRecursiveTask right = new SumRecursiveTask(middle+1,end);//从大到小
                right.fork();
                return left.join() +right.join();
            }
        }
    }
}
